package com.indexingsystem.boss.shiro.service.impl;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import com.indexingsystem.boss.Vo.AuthRoleVo;
import com.indexingsystem.boss.common.INI4j;
import com.indexingsystem.boss.entity.Roles;
import com.indexingsystem.boss.logback.LogCvt;
import com.indexingsystem.boss.shiro.service.IAuthService;
import com.indexingsystem.system.service.IOperationsService;
import com.indexingsystem.system.service.IRolesService;


/**
 * 动态加载权限 Service.
 * 
 * @author Administrator
 *
 */
@Service("authService")
public class AuthServiceImpl implements IAuthService {

	// 注意/r/n前不能有空格
	private static final String CRLF = "\r\n";
	private static final String LAST_AUTH_STR= "/** =authc\r\n";

	@Resource
	@Autowired
	private ShiroFilterFactoryBean shiroFilterFactoryBean;
	
	@Resource
	private IOperationsService iOperationsService;
	
	@Resource
	private IRolesService iRolesService;
	

	@Override
	public String loadFilterChainDefinitions() {
		StringBuffer sb = new StringBuffer();
		// 固定权限，采用读取配置文件
		sb.append(getFixedAuthRule())
	       .append(getDynaAuthRule());
//	       .append(getRestfulOperationAuthRule())
//	       .append(LAST_AUTH_STR);
		
		LogCvt.info("AuthServiceImpl loadFilterChainDefinitions:"+sb.toString());
		return sb.toString();
		
	}

	/**
	 * 从配额文件获取固定权限验证规则串
	 */
	private String getFixedAuthRule() {
		String fileName = "shiro_base_auth.ini";
		ClassPathResource cp = new ClassPathResource(fileName);
		INI4j ini = null;
		try {
			ini = new INI4j(cp.getFile());
		} catch (IOException e) {
			LogCvt.error("加载文件出错。file:"+fileName,e);
		}
		String section = "base_auth";
		Set<String> keys = ini.get(section).keySet();
		StringBuffer sb = new StringBuffer();
		for (String key : keys) {
			String value = ini.get(section, key);
			sb.append(key).append(" = ").append(value).append(CRLF);
		}

		LogCvt.info("AuthServiceImpl getFixedAuthRule:"+sb.toString());
		return sb.toString();
		
		
//		StringBuffer sb = new StringBuffer("");
//	       
//	       ClassPathResource cp = new ClassPathResource("fixed_auth_res.properties");
//	       Properties properties = new OrderedProperties();
//	       try{
//	           properties.load(cp.getInputStream());
//	       } catch(IOException e) {
//	           log.error("loadfixed_auth_res.properties error!", e);
//	           throw new RuntimeException("load fixed_auth_res.properties error!");
//	       }
//	       for(Iteratorits = properties.keySet().iterator();its.hasNext();) {
//	           String key = (String)its.next();
//	           sb.append(key).append(" = ").append(properties.getProperty(key).trim()).append(CRLF);
//	           
//	       }      
//	       returnsb.toString();
		

	}
	
	//根据角色，得到动态权限规则
    private String getDynaAuthRule() {       
       StringBuffer sb = new StringBuffer("");
       Map<String, Set<String>> rules = new HashMap<String,Set<String>>();
       //1、查询角色列表
       List<Roles> rolesList = iRolesService.getRolesList();
       List<AuthRoleVo> authRoleVoList = null;
       
       //2、通过角色id查询功能列表，获取功能       
       if(null != rolesList && rolesList.size()>0){
    	   for(Roles role:rolesList){
    		   authRoleVoList = iRolesService.getRolesCodeOrPageUrl(role.getRoleId());
    		   if(null != authRoleVoList && authRoleVoList.size()>0){
    			   for(AuthRoleVo authRoleVo:authRoleVoList){
    				   if(null != authRoleVo.getUrl()){
    					   String url = authRoleVo.getUrl();
        	               if(!url.startsWith("/")) {
        	                   url = "/"+ url;
        	               }
        	               if(!rules.containsKey(url)) {
        	                   rules.put(url, new HashSet<String>());
        	               }
        	               rules.get(url).add((authRoleVo.getRoleCode()));
    				   }
    			   }
    		   }
    	   }
       }
//       List<Roles> roles = dao.queryEntitys("from Role r left join fetch r.menus", new Object[]{});
//       for(Roles role: roles) {
//           for(Iterator<Menu> menus =role.getMenus().iterator(); menus.hasNext();) {
//              String url = menus.next().getUrl();
//              if(!url.startsWith("/")) {
//                  url = "/"+ url;
//              }
//              if(!rules.containsKey(url)) {
//                  rules.put(url, new HashSet<String>());
//              }
//              rules.get(url).add((role.getRoleCode()));
//           }
//       }
       
       for(Map.Entry<String, Set<String>> entry :rules.entrySet()) {
           sb.append(entry.getKey()).append(" = ").append("authc,roleOrFilter").append(entry.getValue()).append(CRLF);
       }
       LogCvt.info("AuthServiceImpl getDynaAuthRule:"+sb.toString());
       return sb.toString();
    }
    
    
    /**
     * 生成restful风格功能权限规则.
     * 
     * @return
     */
    private String getRestfulOperationAuthRule() {
       List<String> operationsUrl = iOperationsService.queryOperationOrFunctionAll();
       Set<String> restfulUrls = new HashSet<String>();
       for(String operationUrl : operationsUrl) {
           restfulUrls.add(operationUrl);
       }
       StringBuffer sb  = new StringBuffer("");
       for(Iterator<String> urls =  restfulUrls.iterator(); urls.hasNext(); ) {
           String url = urls.next();
           if(! url.startsWith("/")) {
              url = "/"+ url ;
           }
           sb.append(url).append("=").append("authc, rest[").append(url).append("]").append(CRLF);
       }
       LogCvt.info("AuthServiceImpl getRestfulOperationAuthRule:"+sb.toString());
       return sb.toString();
    }
	
	// 此方法加同步锁
	@Override
	public synchronized void reCreateFilterChains() {
		// ShiroFilterFactoryBean shiroFilterFactoryBean =
		// (ShiroFilterFactoryBean)
		// SpringContextUtil.getBean("shiroFilterFactoryBean");
		AbstractShiroFilter shiroFilter = null;
		try {
			shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
		} catch (Exception e) {
			LogCvt.error("getShiroFilter from shiroFilterFactoryBean error!", e);
			throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");
		}

		PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
				.getFilterChainResolver();
		DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();

		// 清空老的权限控制
		manager.getFilterChains().clear();

		shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
		shiroFilterFactoryBean.setFilterChainDefinitions(loadFilterChainDefinitions());
		// 重新构建生成
		Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
		for (Map.Entry<String, String> entry : chains.entrySet()) {
			String url = entry.getKey();
			String chainDefinition = entry.getValue().trim().replace(" ", "");
			manager.createChain(url, chainDefinition);
		}

	}

	public void setShiroFilterFactoryBean(ShiroFilterFactoryBean shiroFilterFactoryBean) {
		this.shiroFilterFactoryBean = shiroFilterFactoryBean;
	}
}